#ifndef _TLISTAPORO_
#define _TLISTAPORO_

#include<iostream>
using namespace std;

#include"tporo.h"

/** \file  tlistaporo.h
 *  \brief Esta es una clase basada en la propiedades y operaciones posibles con una lista de tporos.
 *
 *	Autor: Óscar Toledo Ballester, 48666364c.
 *      Autor: Alejandro Serrano Cases, 74364527f
 *	
 * 	Con esta clase podemos trabajar con un gran numero de operaciones posibles con una lista, con la particularidad de que nuestra lista sera de
 *      tporos. Está compuesta por tres clases: TListaNodo, TListaPosicionicionicion y TListaPoro, todas declaradas entre ellas como amigas.	
 */

class TListaPoro;
class TListaPosicion;
class TListaNodo;

/** \brief Esta es la clase TListaNodo.
 *
 *  Esta es nuestra clase de apoyo TListaNodo, como se puede ver representa a un nodo de la lista, ademas de apuntar al anterior y a su siguiente
 *  también contiene un tporo.
 */

class TListaNodo
{
	friend class TListaPoro;
	friend class TListaPosicion;	
		
	public:
		/** \brief Constructor por defecto de la clase.
		 *  Generamos un Nodo vacio sin anterior ni siguiente.
		 */	
		TListaNodo();
		/** \brief Constructor de copia de la clase.
		 *  Generamos un Nodo copia del pasado como parámetro.
		 *  \param tln TListaNodo que servira para generar la copia.
		 */
		TListaNodo(const TListaNodo& tln);
		/** \brief Destructor de la clase.
		 *  Borramos el complejo que contenga, si lo contiene, ademas de los punteros anterior y siguiente.
		 */
		~TListaNodo();
		/** \brief Operador de asignación de la clase.
		 *  opiamos el Nodo igual el parametro.
		 *  \param tln TListaNodo que servira para copiar en el otro TListaNodo.
		 *  \return Nos devuelve el TListaNodo que llama al metodo modificado para ser igual que el parametro.
		 */
		TListaNodo& operator=(const TListaNodo& tln);	
		/** \brief Operador de comparacion de TListaNodo.
		 *  Compararemos unicamente el TPoro que contiene.
		 *  \param tln TListaNodo que compararemos con el que efectua la llamada.
		 *  \return Nos devuelve un booleano que segun si es cierta la comparacion devolverá true y en caso contrario false.
		 */
		bool operator==(const TListaNodo& tln);		
		/** \brief Operador de no igualdad de TListaNodo.
		 *  Compararemos unicamente el TPoro que contiene.
		 *  \param tln TListaNodo que compararemos con el que efectua la llamada.
		 *  \return Nos devuelve un booleano que segun si es cierta la comparacion devolverá false y en caso contrario true.
		 */
		bool operator!=(const TListaNodo& tln);	
	
	private:
		/** \brief Declaracion de la variable de tipo complejo e.
		 * Este será el poro que contenga el nodo.
		 */
		TPoro e;
		/** \brief Declaracion del puntero al TListaNodo anterior.
		 * Este puntero apuntará al TListaNodo que vaya anteriormente en la lista.
		 */
		TListaNodo *anterior;
		/** \brief Declaracion del puntero al TListaNodo siguiente.
		 * Este puntero apuntará al TListaNodo que vaya posteriormente en la lista.
		 */
		TListaNodo *siguiente;
		
	

};

/** \brief Esta es la clase TListaPoro.
 *
 *  Esta es la clase principal que utiliza como apoyo TListaNodo y TListaPosicionicionicion. Aqui es donde tenemos la posibilidad de operar y efectuar diferentes 
 *  modificaciones, comparaciones, etc... con las listas de TPoros.
 */

class TListaPoro
{
	friend class TListaNodo;
	friend class TListaPosicion;
	
	/** \brief Operador << de TListaPoro.
	 *  Mostramos la lista con el siguiente formato "  ".
	 *  \param os Ostream que recojerá la lista con el formato para mostrar.	
	 *  \param tlp TListaPoro que queremos mostrar.
	 *  \return Nos devuelve un ostream que recoje la lista en el formato adecuado.
         */
	friend ostream& operator<<(ostream& o,const TListaPoro& lista); 

	public:
		/** \brief Constructor por defecto de la clase.
		 *  Creamos una lista vacia con un primero y ultimo apuntando a NULL.
		 */
		TListaPoro();
		/** \brief Constructor de copia de la clase.
		 *  Generamos una lista exactamente igual a la pasada como parámetro.
		 *  \param tlp TListaPoro que servira para generar la copia.
		 */
		TListaPoro(const TListaPoro& tlp);
		/** \brief Destructor de la clase.
		 *  Borramos toda la lista y apuntamos primero y último a NULL.
		 */
		~TListaPoro();
		/** \brief Operador de asignación de la clase.
		 *  Copiamos exactamente la lista pasada como parámetro.
		 *  \param tlp TListaPoro que servira para copiar en el otro TListaPoro.
		 *  \return Nos devuelve el TListaPoro que llama al metodo modificado para ser igual que el parametro.
		 */
		TListaPoro& operator=(const TListaPoro& tlp);
		/** \brief Operador de comparacion de TListaPoro.
		 *  Compararemos toda la lista.
		 *  \param tlp TListaPoro que compararemos con el que efectua la llamada.
		 *  \return Nos devuelve un booleano que segun si es cierta la comparacion devolverá true y en caso contrario false.
		 */
		bool operator==(const TListaPoro& tlp);
		/** \brief Operador de no igualdad de TListaPoro.
		 *  Compararemos toda la lista.
		 *  \param tlp TListaPoro que compararemos con el que efectua la llamada.
		 *  \return Nos devuelve un booleano que segun si es cierta la comparacion devolverá false y en caso contrario true.
		 */
		bool operator!=(const TListaPoro& tlp);
		/** \brief Operador suma de TListaPoro.
		 *  Creamos una lista nueva que contendrá todos los datos de la primera lista concatenados con los de la segunda.
		 *  \param tlp Segundo operando de la suma.
		 *  \return Nos devuelve una lista de complejos nueva que contiene los datos en el mismo orden de la primera y segunda lista.
		 */
		TListaPoro operator+(TListaPoro& tlp);
		/** \brief Operador resta de TListaPoro.
		 *  Creamos una lista nueva que contendrá todos los datos de la primera que la segunda lista no contiene.
		 *  \param tlp Segundo operando de la resta.
		 *  \return Nos devuelve una lista de complejos nueva que contiene los datos en el mismo orden de la primera que no contiene la segunda.
		 */
		TListaPoro operator-(TListaPoro& tlp);
		/** \brief Método EsVacia.
		 *  Comprobamos si la lista tiene algun elemento.
		 *  \return Nos devuelve un booleano que en caso de que sea vacia tendra como valor true y en caso contrario su valor sera false.
		 */
		bool EsVacia() const;
		/** \brief Metodo insertar.
		 *  Creamos un nuevo nodo ,que contendrá el poro que se pasa por referencia, y lo insertamos de forma ordenada en la lista.
		 *  \param p TPoro a insertar en la lista.
		 *  \return Nos devuelve un booleano afirmando o negando la inserción.
		 */
		bool Insertar(const TPoro& p);
		/** \brief Metodo borrar poro.
		 *  Buscamos y borramos de la lista el poro pasado como parámetro.
		 *  \param p TPoro a borrar de la lista.
		 *  \return Nos devuelve un booleano afirmando o negando el borrado.
		 */
		bool Borrar(const TPoro& p);
		/** \brief Metodo borrar TListaPosicionicion.
		 *  Buscamos y borramos de la lista el elemento que ocupa la posicion pasada como parametro.
		 *  \param tlp TListaPosicionicion a borrar de la lista.
		 *  \return Nos devuelve un booleano afirmando o negando el borrado.
		 */
		bool Borrar(const TListaPosicion& tlp);
		/** \brief Metodo obtener.
		 *  Buscamos y obtenemos el complejo que ocupa la posicion pasada como parámetro.
		 *  \param tlp Posicion de la que debemos obtener el complejo.
		 *  \return Nos devuelve el TPoro que ocupa dicha posición.
		 */
		TPoro Obtener(const TListaPosicion& tlp) const;
		/** \brief Metodo buscar.
		 *  Buscamos el poro pasado como parámetro dentro de la lista.
		 *  \param p TPoro a buscar dentro de la lista.
		 *  \return Nos devuelve un booleano afirmando o negando la operación.
		 */
		bool Buscar(const TPoro& p) const;
		/** \brief Metodo Longitud.
		 *  Medimos el tamaño de la lista.
		 *  \return Nos devuelve un entero con el tamaño de la lista.
		 */
		int Longitud() const;
		/** \brief Metodo Primera posición.
		 *  Buscamos la primera posicion.
		 *  \return Nos devuelve un TListaPosicionicion con la primera posición de la lista.
		 */
		TListaPosicion Primera() const;
		/** \brief Metodo Ultima posición.
		 *  Buscamos la ultima posicion.
		 *  \return Nos devuelve un TListaPosicionicion con la ultima posición de la lista.
		 */
		TListaPosicion Ultima() const;

	private:
		/** \brief Declaracion de la variable de tipo TListaNodo primero.
		 * Variable que apunta al primer elemento de la lista.
		 */
		TListaNodo *primero;
		/** \brief Declaracion de la variable de tipo TListaNodo ultimo.
		 * Variable que apunta al ultimo elemento de la lista.
		 */
		TListaNodo *ultimo;

	
};

/** \brief Esta es la clase TListaPosicion.
 *
 *  Esta clase de apoyo refleja la posicion que ocupa en la lista a traves del puntero pos, y nos da facilidades a traves de sus métodos.
 */

class TListaPosicion
{
	friend class TListaPoro;
	friend class TListaNodo;

	public:
		/** \brief Constructor por defecto de la clase.
		 *  Generamos una posicion vacia con pos apuntando a NULL.
		 */
		TListaPosicion();
		/** \brief Constructor de copia de la clase.
		 *  Generamos una posicion copia de la pasada como parámetro.
		 *  \param tlp TListaPosicion que servira para generar la copia.
		 */
		TListaPosicion(const TListaPosicion& tlp);
		/** \brief Destructor de la clase.
		 *  Apuntamos pos a NULL.
		 */
		~TListaPosicion();		
		/** \brief Operador de asignación de la clase.
		 *  opiamos la posicion igual al parámetro.
		 *  \param tlp TListaPosicion que servira para copiar en el otro TListaPosicion.
		 *  \return Nos devuelve el TListaPosicion que llama al metodo modificado para ser igual que el parametro.
		 */
		TListaPosicion& operator=(const TListaPosicion& tlp);
		/** \brief Operador de comparacion de TListaPosicion.
		 *  Compararemos unicamente el puntero pos.
		 *  \param tlp TListaPosicion que compararemos con el que efectua la llamada.
		 *  \return Nos devuelve un booleano que segun si es cierta la comparacion devolverá true y en caso contrario false.
		 */
		bool operator==(const TListaPosicion& tlp);
		/** \brief Operador de no igualdad de TListaPosicion.
		 *  Compararemos unicamente el puntero pos.
		 *  \param tlp TListaPosicion que compararemos con el que efectua la llamada.
		 *  \return Nos devuelve un booleano que segun si es cierta la comparacion devolverá false y en caso contrario true.
		 */
		bool operator!=(const TListaPosicion& tlp);
		/** \brief Metodo Anterior.
		 *  Buscamos la posicion anterior al que efectua la llamada.
		 *  \return Nos devuelve un TListaPosicion correspondiente al anterior del que efectua la llamada.
		 */
		TListaPosicion Anterior() const;
		/** \brief Metodo Siguiente.
		 *  Buscamos la posicion siguiente al que efectua la llamada.
		 *  \return Nos devuelve un TListaPosicion correspondiente al siguiente del que efectua la llamada.
		 */
		TListaPosicion Siguiente() const;
		/** \brief Metodo EsVacia.
		 *  Nos indica si una posicion esta vacia, es decir, si su puntero interno pos apunta a NULL.
		 *  \return Nos devuelve un booleano el cual tendra valor true si esta vacia o valor false en caso contrario.
		 */
		bool EsVacia() const;

	private:
		/** \brief Declaracion del puntero de tipo TListaNodo, denominado pos.
		 * Este puntero apunta a un TListaNodo indicando asi su posicion.
		 */
		TListaNodo *pos;
	
};


#endif
